package com.coderg.gmall.list.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.coderg.gmall.list.dao.GoodsRepository;
import com.coderg.gmall.list.service.GoodsService;
import com.coderg.gmall.model.list.Goods;
import com.coderg.gmall.model.list.SearchAttr;
import com.coderg.gmall.model.list.SearchResponseAttrVo;
import com.coderg.gmall.model.list.SearchResponseTmVo;
import com.coderg.gmall.model.product.BaseAttrInfo;
import com.coderg.gmall.model.product.BaseCategoryView;
import com.coderg.gmall.model.product.BaseTrademark;
import com.coderg.gmall.model.product.SkuInfo;
import com.coderg.gmall.product.ItemProductFeign;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author CoderG
 * @Date 2025/5/26 18:32
 **/
@Service
public class GoodsServiceImpl implements GoodsService {
    @Autowired
    GoodsRepository goodsRepository;
    @Autowired
    ItemProductFeign itemFeign;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    RestHighLevelClient restHighLevelClient;

    /**
     * 将数据库数据导入es  上架
     *
     * @param skuId
     */
    @Override
    public void addSkuFromDbToEs(Long skuId) {
        //对象初始化
        Goods goods = new Goods();
        //根据skuId查询商品的平台属性
        List<BaseAttrInfo> baseAttrInfos = itemFeign.getAttrList(skuId);
        //循环遍历将属性进行类型转换
        List<SearchAttr> searchAttrs = baseAttrInfos.stream().map(c -> {
            SearchAttr searchAttr = new SearchAttr();
            //获取属性id
            searchAttr.setAttrId(c.getId());
            //获取属性的名字
            searchAttr.setAttrName(c.getAttrName());
            //获取属性的值
            searchAttr.setAttrValue(c.getAttrValueList().get(0).getValueName());
            //返回SearchAttr
            return searchAttr;
        }).collect(Collectors.toList());
        //设置属性
        goods.setAttrs(searchAttrs);
        //获取skuinfo的信息
        SkuInfo skuInfo = itemFeign.getSkuInfo(skuId);
        if (skuInfo == null || skuInfo.getId() == null) {
            return;
        }
        //获取分类信息
        BaseCategoryView categoryView = itemFeign.getBaseCategory(skuInfo.getCategory3Id());
        //设置分类信息
        goods.setCategory1Id(categoryView.getCategory1Id());
        goods.setCategory1Name(categoryView.getCategory1Name());
        goods.setCategory2Id(categoryView.getCategory2Id());
        goods.setCategory2Name(categoryView.getCategory2Name());
        goods.setCategory3Id(categoryView.getCategory3Id());
        goods.setCategory3Name(categoryView.getCategory3Name());
        //获取sku的价格
        BigDecimal skuPrice = itemFeign.getSkuPrice(skuId);
        goods.setPrice(skuPrice.doubleValue());
        //品牌信息
        BaseTrademark trademark = itemFeign.getTrademarkByTmId(skuInfo.getTmId());
        goods.setTmId(trademark.getId());
        goods.setTmName(trademark.getTmName());
        goods.setTmLogoUrl(trademark.getLogoUrl());
        //补全其他信息
        goods.setId(skuId);
        goods.setDefaultImg(skuInfo.getSkuDefaultImg());
        goods.setTitle(skuInfo.getSkuName());
        goods.setCreateTime(new Date());
        //保存goods信息
        goodsRepository.save(goods);
    }


    /**
     * 下架商品
     *
     * @param skuId
     * @return
     */
    @Override
    public void lowerGoods(Long skuId) {
        goodsRepository.deleteById(skuId);
    }

    /**
     * 更新热点
     *
     * @param goodsId
     */
    @Override
    public void incrHotScore(Long goodsId) {
        if (goodsId == null) {
            return;
        }
        String hotKey = "good_hot_Score";
        //每访问一次商品详情,对商品的热度值进行+1
        Double score = redisTemplate.opsForZSet().incrementScore("good_hot_Score", goodsId, 1);
        //每访问100次同步一次es的数据
        if (score % 100 == 0) {
            //获取es中的goods数据
            Goods goods = goodsRepository.findById(goodsId).get();
            //设置热度值
            goods.setHotScore(score.longValue());
            //同步至es
            goodsRepository.save(goods);
        }
    }

    /**
     * 搜索商品
     *
     * @param searchCondition
     * @return
     */
    @Override
    public Map<String, Object> searchGoods(Map<String, Object> searchCondition) {
        //参数验证
        if (searchCondition == null && searchCondition.size() == 0) {
            return null;
        }
        HashMap<String, Object> objectObjectHashMap = new HashMap<>();
        try {
            //拼接查询条件
            SearchRequest searchRequest = buildQuery(searchCondition);

            //查询
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            //处理结果
            responseHandle(objectObjectHashMap, searchResponse);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return objectObjectHashMap;
    }

    private SearchRequest buildQuery(Map<String, Object> searchCondition) {
        String title = (String) searchCondition.get("title");
        SearchRequest searchRequest = new SearchRequest("goods");
        SearchSourceBuilder requestBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //标题栏搜索
        if (!StringUtils.isEmpty(title)) {
            boolQuery.must(QueryBuilders.matchQuery("title", title));

        }
        //3级目录搜索  categoryId，id:value
        String category3 = (String) searchCondition.get("category");
        if (!StringUtils.isEmpty(category3)) {
            String[] category3Name = category3.split(":");
            boolQuery.must(QueryBuilders.termQuery("category3Name", category3Name[1]));
        }
        //品牌搜索
        String tmName = (String) searchCondition.get("tmName");
        if (!StringUtils.isEmpty(title)) {
            boolQuery.must(QueryBuilders.matchQuery("tmName", tmName));
        }
        //前端平台属性值查询参数  attr_平台属性名  attr_内存=3:华为
        searchCondition.entrySet().forEach(s -> {
            if (s.getKey().startsWith("attr_")) {
                String attrValue = (String) s.getValue();
                String[] split = attrValue.split(":");
                //获取平台属性值id
                BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
                        .must(QueryBuilders.termQuery("attrs.attrId", Long.valueOf(split[0])))
                        .must(QueryBuilders.termQuery("attrs.attrValue", split[1]));

                boolQuery.must(QueryBuilders.nestedQuery("attrs", boolQueryBuilder, ScoreMode.None));
            }
        });
        //设置价格 "price:2000-3000元  5000元以上
        String price = (String) searchCondition.get("price");
        if (!StringUtils.isEmpty(price)) {
            String priceS = price.replace("元", "").replace("以上", "");
            String[] split = priceS.split(":");
            if (split.length == 1) {
                QueryBuilders.rangeQuery("price")
                        .gte(Long.valueOf(split[0]));
            } else {
                QueryBuilders.rangeQuery("price")
                        .gte(Long.valueOf(split[0])).lt(Long.valueOf(split[1]));
            }
        }

        //设置所有条件
        requestBuilder.query(boolQuery);

        //排序 sort  前端参数  feild   规则 desc asc
        String sortField = (String) searchCondition.get("sortField");
        String sortRule = (String) searchCondition.get("sortRule");
        if (!StringUtils.isEmpty(sortField) || !StringUtils.isEmpty(sortRule)) {

            requestBuilder.sort(sortField, SortOrder.valueOf(sortRule));
        } else {
            //不给条件默认id排序
            requestBuilder.sort("id", SortOrder.DESC);
        }
        //设置分页    固定大小每页50条
        Long pageSize = 50L;
        requestBuilder.size(50);
        String pageNum = (String) searchCondition.get("pageNum");
        Long currentPage = getCurrentPage(pageNum, pageSize);
        requestBuilder.from(currentPage.intValue());

        //品牌聚合
        requestBuilder.aggregation(
                //聚合得到品牌id    terms()这个是起别名
                AggregationBuilders.terms("aggTmId").field("tmId")
                        .subAggregation(AggregationBuilders.terms("aggTmName").field("tmName"))
                        .subAggregation(AggregationBuilders.terms("addTmLog").field("tmLogoUrl"))
                        .size(100)
        );
        //平台属性和值展示
        requestBuilder.aggregation(
                AggregationBuilders.nested("aggAttrs", "attrs")
                        .subAggregation(AggregationBuilders.terms("aggAttrId").field("attrs.attrId")
                                .size(100)
                                .subAggregation(AggregationBuilders.terms("aggAttrValue").field("attrs.attrValue"))
                                .subAggregation(AggregationBuilders.terms("aggAttrName").field("attrs.attrName")))

        );

        //设置高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("<font style='color:red'>");
        highlightBuilder.postTags("</font>");
        requestBuilder.highlighter(highlightBuilder);

        //返回条件
        searchRequest.source(requestBuilder);
        return searchRequest;
    }

    /**
     * 计算当前页
     *
     * @param num
     * @param size
     * @return
     */
    private static Long getCurrentPage(String num, Long size) {
        try {
            Long pageNum = Long.valueOf(num);
            if (pageNum <= 0 || pageNum >= 200) {
                pageNum = 1L;
            }
            Long currentPage = (pageNum - 1) * size;
            return currentPage;
        } catch (Exception e) {
            return 1L;
        }


    }


    private void responseHandle(HashMap<String, Object> objectObjectHashMap, SearchResponse searchResponse) throws IllegalAccessException, InvocationTargetException {
        SearchHits hits = searchResponse.getHits();
        ArrayList<Object> goodsData = new ArrayList<>();
        SearchHit[] hitsHits = hits.getHits();
        for (SearchHit hitsHit : hitsHits) {
            //json对象字符串
            String sourceAsString = hitsHit.getSourceAsString();
            Goods goods = JSONObject.parseObject(sourceAsString, Goods.class);
            goodsData.add(goods);
            //获取高亮部分
            HighlightField highTitleField = hitsHit.getHighlightFields().get("title");
            if (highTitleField != null) {

                Text[] fragments = highTitleField.getFragments();
                if (fragments != null && fragments.length > 0) {
                    String title = "";
                    for (Text fragment : fragments) {
                        title += fragment;
                    }
                    //替换原title
                    goods.setTitle(title);
                }
            }

           /*  Map<String, Object> sourceAsMap = hitsHit.getSourceAsMap();
            Goods goods = new Goods();
            BeanUtils.populate(goods, sourceAsMap); */
        }
        //取出聚合的品牌信息
        Aggregations aggregations = searchResponse.getAggregations();

        List<SearchResponseTmVo> tmInfo = getTmInfo(aggregations);
        //取出平台属性和值
        List<SearchResponseAttrVo> searchResponseAttrVoList
                = getAttrNameAndValue(aggregations);

        objectObjectHashMap.put("goods", goodsData);
        objectObjectHashMap.put("tmInfo", tmInfo);
        objectObjectHashMap.put("AttrAndValues", searchResponseAttrVoList);

    }

    private List<SearchResponseAttrVo> getAttrNameAndValue(Aggregations aggregations) {
        //先获取nested集合聚合结果
        ParsedNested aggAttrs = aggregations.get("aggAttrs");
        //在获取平台属性id的聚合结果
        ParsedLongTerms aggAttrId = aggAttrs.getAggregations().get("aggAttrId");
        return aggAttrId.getBuckets().stream().map(AggattrId -> {
                    SearchResponseAttrVo searchResponseAttrVo = new SearchResponseAttrVo();
                    long attrId = AggattrId.getKeyAsNumber().longValue();
                    searchResponseAttrVo.setAttrId(attrId);
                    ParsedStringTerms aggAttrNAme = AggattrId.getAggregations().get("aggAttrName");
                    if (!aggAttrNAme.getBuckets().isEmpty()) {
                        String attrName = aggAttrNAme.getBuckets().get(0).getKeyAsString();
                        searchResponseAttrVo.setAttrName(attrName);
                    }

                    ParsedStringTerms aggAttrValue = AggattrId.getAggregations().get("aggAttrValue");
                    if (!aggAttrValue.getBuckets().isEmpty()) {
                        List<String> attrValueList = aggAttrValue.getBuckets().stream().map(agAttrValue -> agAttrValue.getKeyAsString()
                        ).collect(Collectors.toList());
                        searchResponseAttrVo.setAttrValueList(attrValueList);
                    }
                    return searchResponseAttrVo;
                }
        ).collect(Collectors.toList());

    }

    private List<SearchResponseTmVo> getTmInfo(Aggregations aggregations) {
        ParsedLongTerms aggTmId = aggregations.get("aggTmId");
        return aggTmId.getBuckets().stream().map(tmIdBucket -> {
            //设置品牌vo返回前端
            SearchResponseTmVo searchResponseTmVo = new SearchResponseTmVo();
            //获取品牌id
            long timId = tmIdBucket.getKeyAsNumber().longValue();
            searchResponseTmVo.setTmId(timId);
            //每一个品牌id都有子聚合name log
            ParsedStringTerms aggTmName = tmIdBucket.getAggregations().get("aggTmName");
            if (!aggTmName.getBuckets().isEmpty()) {
                String tmName = aggTmName.getBuckets().get(0).getKeyAsString();
                searchResponseTmVo.setTmName(tmName);
            }

            ParsedStringTerms addTmLog = tmIdBucket.getAggregations().get("addTmLog");
            if (!addTmLog.getBuckets().isEmpty()) {
                String TmLogUrl = addTmLog.getBuckets().get(0).getKeyAsString();
                searchResponseTmVo.setTmLogoUrl(TmLogUrl);
            }
            return searchResponseTmVo;
        }).collect(Collectors.toList());

    }

}
